﻿//======================================================================


// CLR版本:            	2.0.50727.3053
// 新建项输入的名称: 	WebUtil
// 文件名称 : 		    WebUtil
// 创建时间: 		    12/17/2009 4:24:33 PM
// 创 建 人: 		    kamiff
// 文件说明:            用于提供页面操作的工具方法

// 最后修改人:
// 修改说明:
// 修改时间:     
//======================================================================

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web;

using System.Web.UI.WebControls;
using Efficient.Domain;
using System.Web.UI;

namespace Efficient
{
    /// <summary>
    /// Web参数来源的枚举
    /// </summary>
    public enum WebParamType
    {
        All,     //全部
        Url,
        Form,
        ServerVariables,
        Cookies
    }

    /// <summary>
    /// WebUtil 描述
    /// </summary>
    public static class WebUtil
    {
        #region 获取Url参数值

        /// <summary>
        /// 获取一个Web 参数的Int32类型的值,如果该参数不存在或者无法转换成Int32则返回0
        /// </summary>
        /// <param name="paramName">Web 参数的名称</param>
        /// <returns>Int32类型的值</returns>
        public static int GetIntQueryString(string paramName)
        {
            return GetIntQueryString(paramName,WebParamType.All, 0);
        }

        /// <summary>
        /// 获取一个Web 参数的Int32类型的值,如果该参数不存在或者无法转换成Int32则返回0
        /// </summary>
        /// <param name="paramName">Web 参数的名称</param>
        /// <param name="paramType">参数来源的枚举</param>
        /// <returns></returns>
        public static int GetIntQueryString(string paramName, WebParamType paramType)
        {
            return GetIntQueryString(paramName, paramType, 0);
        }

        /// <summary>
        /// 获取一个Web 参数的Int32类型的值,如果该参数不存在或者无法转换成Int32则返回defaultValue的值
        /// </summary>
        /// <param name="paramName">Web 参数的名称</param>
        /// <param name="defaultValue">获取失败时返回的值</param>
        /// <returns></returns>
        public static int GetIntQueryString(string paramName, int defaultValue)
        {
            return GetIntQueryString(paramName, WebParamType.All, defaultValue);
        }
        /// <summary>
        /// 获取一个Web 参数的Int32类型的值,如果该参数不存在或者无法转换成Int32返回则defaultValue的值
        /// </summary>
        /// <param name="paramName">Web 参数的名称</param>
        /// <param name="paramType">参数来源枚举</param>
        /// <returns>Int32类型的值</returns>
        /// <param name="defaultValue">默认值,如果没有找到该参数或者参数类型错误这返回defaultValue的值</param>
        public static int GetIntQueryString(string paramName,WebParamType paramType, int defaultValue)
        {
            string data = GetRequestParameterValue(paramName, paramType);
            if (!string.IsNullOrEmpty(data))
            {
                return SafeConvert.ToInt32(data.Trim(), defaultValue);
            }
            return defaultValue;
        }

        /// <summary>
        /// 获取一个Web 参数的Int64类型的值,如果该参数不存在或者无法转换成Int64则返回0
        /// </summary>
        /// <param name="paramName">Web 参数的名称</param>
        /// <returns>Int64类型的值</returns>
        public static long GetLongQueryString(string paramName)
        {
            return GetLongQueryString(paramName,WebParamType.All, 0);
        }

        /// <summary>
        /// 获取一个Web 参数的Int64类型的值,如果该参数不存在或者无法转换成Int64则返回0
        /// </summary>
        /// <param name="paramName">Web 参数的名称</param>
        /// <param name="paramType">参数来源枚举</param>
        /// <returns></returns>
        public static long GetLongQueryString(string paramName, WebParamType paramType)
        {
            return GetLongQueryString(paramName, paramType, 0);
        }

        /// <summary>
        /// 获取一个Web 参数的Int64类型的值,如果该参数不存在或者无法转换成Int64则返回defaultValue的值
        /// </summary>
        /// <param name="paramName">Web 参数的名称</param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static long GetLongQueryString(string paramName, long defaultValue)
        {
            return GetLongQueryString(paramName, WebParamType.All, defaultValue);
        }

        /// <summary>
        /// 获取一个URL 参数的Int64类型的值,如果该参数不存在或者无法转换成Int64返回则defaultValue的值
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="paramType"></param>
        /// <returns></returns>
        /// <param name="defaultValue"></param>
        public static long GetLongQueryString(string paramName, WebParamType paramType, long defaultValue)
        {
            string data = GetRequestParameterValue(paramName, paramType);
            if (!string.IsNullOrEmpty(data))
            {
                return SafeConvert.ToInt64(data.Trim(), defaultValue);
            }
            return defaultValue;
        }

        /// <summary>
        /// Get a decimal URL parameter
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="paramType"></param>
        /// <returns></returns>
        /// <param name="defaultValue"></param>
        public static decimal GetDecimalQueryString(string paramName, WebParamType paramType, decimal defaultValue)
        {
            string data = GetRequestParameterValue(paramName, paramType);
            if (!string.IsNullOrEmpty(data))
            {
                return SafeConvert.ToDecimal(data.Trim(), defaultValue);
            }
            return defaultValue;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="paramType"></param>
        /// <returns></returns>
        public static decimal GetDecimalQueryString(string paramName, WebParamType paramType)
        {
            const decimal returnValue = 0M;
            return GetDecimalQueryString(paramName, paramType, returnValue);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static decimal GetDecimalQueryString(string paramName, decimal defaultValue)
        {
            return GetDecimalQueryString(paramName, WebParamType.All, defaultValue);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="paramName"></param>
        /// <returns></returns>
        public static decimal GetDecimalQueryString(string paramName)
        {
            const decimal returnValue = 0M;
            return GetDecimalQueryString(paramName,WebParamType.All, returnValue);
        }

        /// <summary>
        /// Get a string URL parameter
        /// </summary>
        /// <param name="paramName"></param>
        /// <returns></returns>
        public static string GetStringQueryString(string paramName)
        {
            return GetStringQueryString(paramName,WebParamType.All, string.Empty);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="paramType"></param>
        /// <returns></returns>
        public static string GetStringQueryString(string paramName, WebParamType paramType)
        {
            return GetStringQueryString(paramName, paramType, string.Empty);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string GetStringQueryString(string paramName, string defaultValue)
        {
            return GetStringQueryString(paramName, WebParamType.All, defaultValue);
        }
        /// <summary>
        /// Get a string URL parameter, return default value if parameter not found.
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="paramType"></param>
        /// <returns></returns>
        /// <param name="defaultValue"></param>
        public static string GetStringQueryString(string paramName, WebParamType paramType, string defaultValue)
        {
            string data = GetRequestParameterValue(paramName, paramType);
            if (!string.IsNullOrEmpty(data))
            {
                return data.Trim();
            }
            return defaultValue;
        }


        /// <summary>
        /// Get a DateTime URL parameter
        /// </summary>
        /// <param name="paramName"></param>
        /// <returns></returns>
        public static DateTime GetDateQueryString(string paramName)
        {
            return GetDateQueryString(paramName, WebParamType.All, new DateTime(1900,1,1));
        }

        /// <summary>
        /// Get a DateTime URL parameter
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="paramType"></param>
        /// <returns></returns>
        public static DateTime GetDateQueryString(string paramName, WebParamType paramType)
        {
            return GetDateQueryString(paramName, paramType, new DateTime(1900, 1, 1));
        }

        /// <summary>
        /// Get a DateTime URL parameter
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static DateTime GetDateQueryString(string paramName, DateTime defaultValue)
        {
            return GetDateQueryString(paramName, WebParamType.All, defaultValue);
        }
        /// <summary>
        /// Get a DateTime URL parameter, return default value if parameter not found.
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="paramType"></param>
        /// <returns></returns>
        /// <param name="defaultValue"></param>
        public static DateTime GetDateQueryString(string paramName, WebParamType paramType, DateTime defaultValue)
        {
            string data = GetRequestParameterValue(paramName, paramType);
            if (!string.IsNullOrEmpty(data))
            {
                return SafeConvert.ToDateTime(data.Trim(), defaultValue);
            }
            return defaultValue;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="paramName"></param>
        /// <param name="paramType"></param>
        /// <returns></returns>
        private static string GetRequestParameterValue(string paramName, WebParamType paramType)
        {
            switch (paramType)
            {
                case WebParamType.All:
                    return HttpContext.Current.Request.Params[paramName];
                case WebParamType.Cookies:
                    HttpCookie cookie = HttpContext.Current.Request.Cookies[paramName];
                    return cookie == null ? null : cookie.Value;
                case WebParamType.Form:
                    return HttpContext.Current.Request.Form[paramName];
                case WebParamType.ServerVariables:
                    return HttpContext.Current.Request.ServerVariables[paramName];
                case WebParamType.Url:
                    return HttpContext.Current.Request.QueryString[paramName];
                default:
                    return HttpContext.Current.Request.Params[paramName];
            }
        }

        #endregion

        #region 选择下拉列表中的项
        /// <summary>
        /// 同时选择列表控件中的多个项
        /// </summary>
        /// <param name="list">列表控件</param>
        /// <param name="value">项的值以 split 的值为分割符</param>
        /// <param name="split">用于分割要选择的项值的分割符</param>
        public static void TrySelectItemByMultiValue(ListControl list, string value, char split)
        {
            if (list == null || value == null)
            {
                return;
            }
            list.SelectedIndex = -1;
            string[] values = value.Split(split);
            if (values.Length == 0)
            {
                return;
            }
            foreach (string s in values)
            {
                ListItem item = list.Items.FindByValue(s);
                if (item != null)
                {
                    item.Selected = true;
                }
            }
        }

        /// <summary>
        /// 同时选择列表控件中的多个项
        /// </summary>
        /// <param name="list">列表控件</param>
        /// <param name="value">项的值以 ',' 的值为分割符</param>
        public static void TrySelectItemByMultiValue(ListControl list, string value)
        {
            TrySelectItemByMultiValue(list, value, ',');
        }

        /// <summary>
        /// 选择单个列表控件的值
        /// </summary>
        /// <param name="list">列表控件</param>
        /// <param name="value">要选中项的值</param>
        /// <returns>如果选中成功则返回true</returns>
        public static bool TrySelectItemByValue(ListControl list, object value)
        {
            if (value == null || list == null)
            {
                return false;
            }
            list.SelectedIndex = -1;
            ListItem item = list.Items.FindByValue(value.ToString());
            if (item != null)
            {
                item.Selected = true;
                return true;
            }
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public static string GetMultiSelectedValue(ListControl list)
        {
            return GetMultiSelectedValue(list, ",");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="list"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        public static string GetMultiSelectedValue(ListControl list, string separator)
        {
            StringBuilder sbValue = new StringBuilder();
            foreach (ListItem item in list.Items)
            {
                if (item.Selected)
                {
                    sbValue.AppendFormat("{0}{1}", item.Value, separator);
                }
            }
            if (sbValue.Length > 0)
            {
                return sbValue.ToString(0, sbValue.Length - 1);
            }
            return string.Empty;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public static string GetSelectedText(ListControl list)
        {
            foreach (ListItem item in list.Items)
            {
                if (item.Selected)
                {
                    return item.Text;
                }
            }
            return string.Empty;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="list"></param>
        /// <param name="separator"></param>
        /// <returns></returns>
        public static string GetMultiSelectedText(ListControl list, string separator)
        {
            StringBuilder sbValue = new StringBuilder();
            foreach (ListItem item in list.Items)
            {
                if (item.Selected)
                {
                    sbValue.AppendFormat("{0}{1}", item.Text, separator);
                }
            }
            if (sbValue.Length > 0)
            {
                return sbValue.ToString(0, sbValue.Length - separator.Length);
            }
            return string.Empty;
        }

        public static string GetDropDownListSelectValue(DropDownList ddl, string nullValue)
        {
            return ddl.SelectedValue != nullValue ? ddl.SelectedValue : null;
        }
        #endregion

        #region 绑定树形下拉列表
        /// <summary>
        /// 绑定分类下拉列表,并产生树形排列
        /// </summary>
        /// <typeparam name="T">实现ITreeableEntity的实体类型参数</typeparam>
        /// <typeparam name="Id">实体的Id的类型参数</typeparam>
        /// <param name="ddl">下拉列表</param>
        /// <param name="categoryList">全部的分类实体集合</param>
        public static void BindCategoriesTree<T, Id>(DropDownList ddl, ICollection<T> categoryList)
            where T : ITreeableEntity<T, Id>
        {
            BindCategoriesTree<T, Id>(ddl, categoryList, false);
        }
        /// <summary>
        /// 绑定分类下拉列表,并产生树形排列
        /// </summary>
        /// <typeparam name="T">实现ITreeableEntity的实体类型参数</typeparam>
        /// <typeparam name="Id">实体的Id的类型参数</typeparam>
        /// <param name="ddl">下拉列表</param>
        /// <param name="tryFindRoot">尝试去寻找Parent不存在于categoryList中的项作为根，应该重写T的Equals方法</param>
        /// <param name="categoryList">全部的分类实体集合</param>
        public static void BindCategoriesTree<T, Id>(DropDownList ddl, ICollection<T> categoryList, bool tryFindRoot)
            where T : ITreeableEntity<T, Id>
        {
            ddl.Items.Clear();
            StringBuilder sbPrefix = new StringBuilder();
            ICollection<T> rootCategories = BuildRootCategories<T, Id>(categoryList, tryFindRoot);
            BindCategoriesTreeInner<T, Id>(ddl, rootCategories, 0, sbPrefix);
        }

        private static void BindCategoriesTreeInner<T, Id>(ListControl ddl, ICollection<T> categoryList, int deep,
                                                           StringBuilder sbPrefix) where T : ITreeableEntity<T, Id>
        {
            int i = 0;
            foreach (T item in categoryList)
            {
                bool hasChild = item.Childs.Count > 0 ? true : false;
                bool isLast = (i + 1) == categoryList.Count ? true : false;
                ListItem listItem =
                    new ListItem(string.Concat(BuildTreeItemPreFixIcon(hasChild, isLast, deep, sbPrefix), item.Name),
                                 item.ID.ToString());
                ddl.Items.Add(listItem);
                if (hasChild)
                {
                    BindCategoriesTreeInner<T, Id>(ddl, item.Childs, deep + 1, sbPrefix);
                }
                i++;
            }
        }

        private static string BuildTreeItemPreFixIcon(bool hasChild, bool isLast, int deep, StringBuilder sbPrefix)
        {
            if (sbPrefix.Length > 0)
            {
                sbPrefix.Remove(0, sbPrefix.Length);
            }
            for (int i = 0; i < deep; i++)
            {
                sbPrefix.Append("│");
            }
            sbPrefix.Append(isLast ? "└" : "├");
            if (hasChild)
            {
                sbPrefix.Append("┬");
            }
            else
            {
                sbPrefix.Append("─");
            }
            return sbPrefix.ToString();
        }

        private static ICollection<T> BuildRootCategories<T, Id>(ICollection<T> categories, bool tryFindRoot)
            where T : ITreeableEntity<T, Id>
        {
            ICollection<T> returnValue = new List<T>();
            foreach (T item in categories)
            {
                bool tryMatch = tryFindRoot && !categories.Contains(item.Parent);
                if ((Equals(item.Parent, default(T)) || tryMatch) && !returnValue.Contains(item))
                {
                    item.Childs = new List<T>();
                    BuildInner<T, Id>(categories, item);
                    returnValue.Add(item);
                }
            }
            return returnValue;
        }

        private static void BuildInner<T, Id>(IEnumerable<T> categories, T entity) where T : ITreeableEntity<T, Id>
        {
            entity.Childs = new List<T>();
            foreach (T item in categories)
            {
                if (!Equals(item.Parent, default(T)) && item.Parent.ID.Equals(entity.ID) &&
                    !entity.Childs.Contains(item))
                {
                    BuildInner<T, Id>(categories, item);
                    entity.Childs.Add(item);
                }
            }
        }
        #endregion

        public static string GetControlHtmlOutput(Control uc)
        {
            StringBuilder build = new StringBuilder();
            using (HtmlTextWriter htmlWriter = new HtmlTextWriter(new StringWriter(build)))
            {
                uc.RenderControl(htmlWriter);
                htmlWriter.Flush();
                return build.ToString();
            }
        }

        public static T LoadControl<T>(TemplateControl page, string path) where T : Control
        {
            return page.LoadControl(path) as T;
        }
    }
}